package com.redstar.HappyRefresh.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.redstar.HappyRefresh.constant.RedisConstant;
import com.redstar.HappyRefresh.mapper.FollowMapper;
import com.redstar.HappyRefresh.pojo.BasePage;
import com.redstar.HappyRefresh.pojo.Follow;
import com.redstar.HappyRefresh.pojo.Video;
import com.redstar.HappyRefresh.service.FeedService;
import com.redstar.HappyRefresh.service.FollowService;
import com.redstar.HappyRefresh.service.VideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;


@Service
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow> implements FollowService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    @Lazy
    private VideoService videoService;
    @Autowired
    private FeedService feedService;

    @Override
    public int getFollowCount(Long userId) { // 查询指定用户的关注数量
        try {
            return count(new LambdaQueryWrapper<Follow>().eq(Follow::getUserId, userId));
        } catch (Exception e) {
            throw new RuntimeException("getFollowCount方法出错：" + e.getMessage());
        }
    }

    @Override
    public int getFansCount(Long userId) { // 查询指定用户的粉丝数量
        try {
            return count(new LambdaQueryWrapper<Follow>().eq(Follow::getFollowId, userId));
        } catch (Exception e) {
            throw new RuntimeException("getFansCount方法出错：" + e.getMessage());
        }
    }

    @Override
    public List<Long> getFollowList(BasePage basePage, Long userId) { // 查询指定用户的关注列表
        List<Long> store = null;
        if (basePage == null) { // 不需要查询分页数据
            Set<Object> set = redisTemplate.opsForZSet().reverseRange(RedisConstant.USER_FOLLOW + userId, 0, -1);
            if (ObjectUtils.isEmpty(set)) { //  缓存为空，从数据库中查询
                List<Follow> list = list(new LambdaQueryWrapper<Follow>().eq(Follow::getUserId, userId));
                store = list.stream().map(Follow::getFollowId).collect(Collectors.toList());
            } else {
                store = set.stream().map(o -> (Long.valueOf(o.toString()))).collect(Collectors.toList());
            }
            return store;
        }
        // 需要分页查询
        Long pageNum = basePage.getPageNum();
        Long pageSize = basePage.getPageSize();
        if (Boolean.TRUE.equals(redisTemplate.hasKey(RedisConstant.USER_FOLLOW + userId))) {
            long start = (pageNum - 1) * pageSize;
            long end = pageNum * pageSize - 1;
            Long size = redisTemplate.opsForZSet().size(RedisConstant.USER_FOLLOW + userId);
            if (size != null && end > size) {
                end = -1;
            }
            Set<ZSetOperations.TypedTuple<Object>> setPage = redisTemplate.opsForZSet().reverseRangeWithScores(RedisConstant.USER_FOLLOW + userId, start, end);
            if (ObjectUtils.isEmpty(setPage)) {
                List<Follow> list = page(basePage.page(), new LambdaQueryWrapper<Follow>().eq(Follow::getUserId, userId)).getRecords();
                store = list.stream().map(Follow::getFollowId).collect(Collectors.toList());
            } else {
                store = setPage.stream().map(t -> Long.valueOf(Objects.requireNonNull(t.getValue()).toString())).collect(Collectors.toList());
            }
        }
        return store;
    }

    @Override
    public List<Long> getFansList(BasePage basePage, Long userId) { // 查询指定用户的粉丝列表
        List<Long> store = null;
        // 不需要查询分页数据
        if (basePage == null) {
            Set<Object> set = redisTemplate.opsForZSet().reverseRange(RedisConstant.USER_FANS + userId, 0, -1);
            if (ObjectUtils.isEmpty(set)) { //  缓存为空，从数据库中查询
                List<Follow> list = list(new LambdaQueryWrapper<Follow>().eq(Follow::getFollowId, userId));
                store = list.stream().map(Follow::getUserId).collect(Collectors.toList());
            } else {
                store = set.stream().map(o -> (Long.valueOf(o.toString()))).collect(Collectors.toList());
            }
            return store;
        }
        // 需要分页查询
        Long pageNum = basePage.getPageNum();
        Long pageSize = basePage.getPageSize();
        if (Boolean.TRUE.equals(redisTemplate.hasKey(RedisConstant.USER_FANS + userId))) {
            long start = (pageNum - 1) * pageSize;
            long end = pageNum * pageSize - 1;
            Long size = redisTemplate.opsForZSet().size(RedisConstant.USER_FANS + userId);
            if (size != null && end > size) {
                end = -1;
            }
            Set<ZSetOperations.TypedTuple<Object>> setPage = redisTemplate.opsForZSet().reverseRangeWithScores(RedisConstant.USER_FANS + userId, start, end);
            if (ObjectUtils.isEmpty(setPage)) {
                List<Follow> list = page(basePage.page(), new LambdaQueryWrapper<Follow>().eq(Follow::getFollowId, userId)).getRecords();
                store = list.stream().map(Follow::getUserId).collect(Collectors.toList());
            } else {
                store = setPage.stream().map(t -> Long.valueOf(Objects.requireNonNull(t.getValue()).toString())).collect(Collectors.toList());
            }
        }
        return store;
    }

    @Override
    public String followUser(Long userId, Long followsUserId) { // 关注或取关
        Follow follow = Follow.builder().followId(followsUserId).userId(userId).build();
        try {
            // follow表的follow_id字段和user_id字段有唯一索引，重复添加会抛出异常
            // 插入成功说明是关注，插入失败说明是取关
            save(follow); // 插入
            Date date = new Date();
            // 关注列表
            redisTemplate.opsForZSet().add(RedisConstant.USER_FOLLOW + userId, followsUserId.toString(), date.getTime());
            // 粉丝列表
            redisTemplate.opsForZSet().add(RedisConstant.USER_FANS + followsUserId, userId.toString(), date.getTime());
            return "已关注";
        } catch (Exception e) { // 取关
            remove(new LambdaQueryWrapper<Follow>().eq(Follow::getFollowId, followsUserId).eq(Follow::getUserId, userId)); // 删除
            // 关注列表
            redisTemplate.opsForZSet().remove(RedisConstant.USER_FOLLOW + userId, followsUserId);
            // 粉丝列表
            redisTemplate.opsForZSet().remove(RedisConstant.USER_FANS + followsUserId, userId);
            // 删除userId的收件箱中followsUserId的视频
            List<Video> videoList = videoService.list(new LambdaQueryWrapper<Video>().eq(Video::getUserId, followsUserId).eq(Video::getOpen, 0).select(Video::getId));
            feedService.deleteInBoxFeed(userId, videoList.stream().map(Video::getId).collect(Collectors.toList()));
            return "已取关";
        }
    }

    @Override
    public Boolean followState(Long followId, Long userId) { // userId是否关注followId
        if (followId == null || userId == null) { // 游客登录或用户不存在
            return false;
        }
        long count = count(new LambdaQueryWrapper<Follow>().eq(Follow::getFollowId, followId).eq(Follow::getUserId, userId));
        return count == 1;
    }
}
